package study.JavaAdvanced;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.*;
import java.util.Arrays;

/**
 * date:2025.11.18
 * title:网络编程
 * author:fzy
 */

/*
网络编程：在网络通信协议下，实现网络互联的不同计算机运行程序间的数据交换
 三要素：
 1.ip：每台计算机指定的标识号，用来识别识别发送的计算机
 2.端口：本质上是两个应用程序的通过新，端口号可以唯一标识设备程序
 3.协议：对设备的传输格式，速率规定
 */
/*
ip地址：
    ipv4：每个主机分配一个32bit的地址，按照tcp/i规定
    ipv6: 128位地址长度，16个字节一组，分成8组十六进制数
    常用命令：ipconfig
            ping 地址
    特殊ip：127.0.0.1：回送地址，可以代表本机地址，用来测试
 */
public class Java_12 {
    public static void main(String[] arg){
        try{
//          MyInetAddress.getInetAddress();
//            MyInetAddressd.UdpReceive();
//            TCPClass.TcpTest();
            ServerDemo_Tcp.ServerTest();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }
}

/*
InetAddress :表示internet协议地址。
1.static InetAddress getByName(String host)  host可以是ip也可以是计算机名
 */
class MyInetAddressd{
    static void getInetAddress() throws UnknownHostException {
        InetAddress inetAddress = InetAddress.getByName("DESKTOP-1UQ5H6H");
        String HostName = inetAddress.getHostName();
        System.out.println(HostName);
        String ipName  = inetAddress.getHostAddress();
        System.out.println(ipName);
    }
    /*
    端口：设备应用程序的唯一标识
    端口号：两个字节表示的整数，取值为0~65532
    普通的程序不要用0~1023端口
     */
    /*
    协议：链接或者通信的规则
    UDP:用户数据报协议：数据的发送端和接收端不建立逻辑链接，消耗资源小，通信效率高
    通常用于音频，视频，不保证数据的完整性，因此重要协议不建立使用UDP
    TCP：传输控制协议，发送端和接收端建立逻辑链接，明确客户端和服务端，每次链接创建都需要经过三次握手
    1.第一次：客户端向服务器发送链接请求
    2.第二次：服务端回复响应
    3.第三次：客户端再次向服务端通信，确认链接
    上传文件，下载文件，浏览网页
    //好困啊我草草草啊从哦啊草丛凹槽凹槽哦草哦草
     */

    /*
    UDP通信原理：在通信两端各自简历Socket对象，但是这两个对象知识基于协议通信双发而言，没有所谓的客户端和服务端
    java提供了DatagramSocket类作为基于UDP协议的socket
     */
    /*
    1.创建发送端的Socket对象
    2.创建数据打包
    3.使用Socket对象发送
    4.关闭发送端
     */
    static void UdpPost() throws IOException {
        //1.创建socket对象
        DatagramSocket ds = new DatagramSocket();
        //2.创建数据打包
        byte[] bys = "hello".getBytes();
        int length = bys.length;
        int port = 10086;
        InetAddress inetAddress  = InetAddress.getByName("7.247.153.165");
        DatagramPacket datagramPacket = new DatagramPacket(bys,length,inetAddress,port);
        //3.发送
        ds.send(datagramPacket);
        //4.关闭
        ds.close();
    }
    /*
    1.创建接收端的socket对象
    2.创建数据包，用来接收数据
    3.调用DatagramSocket对象接收数据
    4.解析数据，输出
    5.关闭接收端
     */
    static void UdpReceive() throws IOException {
        DatagramSocket datagramSocket = new DatagramSocket(10086);
        byte[] bys = new byte[1024];
        DatagramPacket dp = new DatagramPacket(bys,bys.length);
        datagramSocket.receive(dp);
        int length = dp.getLength();
        byte[] gBys =  dp.getData();
        String dataString = new String(gBys,0,length);
        System.out.println("数据是"+dataString);
        datagramSocket.close();
    }
}

/*
Tcp是一种可靠的网路协议，两端各自建立一个socket对象，从而在两端形成网络虚拟链路
使用socket代表两端的通信端口，通过socket产生的IO流实现网络通信
java为客户端提供了Socket类，为服务器提供了ServerSocket类
 */
class TCPClass{

    //发送数据步骤
    /*
    1.创建客户端的socket对象
    2.获取输出流。写数据
    3.释放资源
     */
    static void TcpTest() throws IOException {
        //Socket (InetAddress address,int port)
//        Socket s = new Socket(InetAddress.getByName("7.247.153.221"),8080);
        Socket s = new Socket("7.247.153.221",8080);
        OutputStream os = s.getOutputStream();
        os.write("hello".getBytes());
        os.close();
        s.close();
    }

    /*
    1.创建服务器的Socket对象(ServerSocket)
    2.获取输入流，读数据，并把数据显示在控制台
    3.释放资源
     */
    static void tcpReceive() throws IOException {
    ServerSocket ss = new ServerSocket(8080);
    //ss.accept() 监听要连接到套接字并接受他
    Socket s = ss.accept();
    //获取输入流,读数据
        InputStream is = s.getInputStream();
        byte[] bys = new byte[1024];
        int len = is.read(bys);
        String data = new String(bys,0,len);
        System.out.println("数据是:"+data);
    }

}

class ServerDemo_Tcp{
    static void ServerTest() throws IOException {
        ServerSocket ss = new ServerSocket(8080);
        Socket  s = ss.accept();
        InputStream is = s.getInputStream();
        byte[] bys = new byte[1024];
       int le =  is.read(bys);
        System.out.println("服务器"+new String(bys,0,le));
        OutputStream os = s.getOutputStream();
        os.write("数据已经收到".getBytes());
        ss.close();

    }
}
